﻿using System;
using System.Collections.Generic;
using USNetFramework.Network;
using USNetFramework.Utils;

namespace USNetFramework.RPC
{
    public delegate NetMsg OnReceivedServerRequest(NetPacket _packet);

    public class RpcManager
    {
        static uint id = 0;
        private Dictionary<uint, RpcObject> m_dictRequestSession;
        private event OnReceivedServerRequest ReceivedEvent;

        // 单例
        static RpcManager instance;
        public static RpcManager Instance
        {
            get
            {
                if (null == instance)
                    instance = new RpcManager();
                return instance;
            }
        }

        private RpcManager()
        {
            m_dictRequestSession = new Dictionary<uint, RpcObject>();
        }

        private uint GenSessionID()
        {
            return (id++==0)?(id++):id;
        }

        public void RegisterServerRequestHandler(OnReceivedServerRequest _handler)
        {
            ReceivedEvent += _handler;
        }

        public void UnregisterServerRequestHandler(OnReceivedServerRequest _handler)
        {
            ReceivedEvent -= _handler;
        }

        public virtual bool SendRpc(NetPacket _packet, RpcEvent _event)
        {
            RpcObject rpcObj = new RpcObject(_event);
            _packet.SessionID = GenSessionID();
            _packet.RequestType = EnumRequestType.Request;
            RpcObject existRpcObj;
            if (m_dictRequestSession.TryGetValue(_packet.SessionID, out existRpcObj))
            {
                TimeSpan timeSpan = DateTime.Now - existRpcObj.RpcTime;
                long cost = (long)Math.Round(timeSpan.TotalSeconds);
                if (cost > NetOption.RPCTimeOut)
                    m_dictRequestSession.Remove(_packet.SessionID);
                else
                    return false;
            }
            m_dictRequestSession.Add(_packet.SessionID, rpcObj);
            return true;
        }

        public virtual void Received(NetPacket _packet, NetSocket _socket)
        {
            if (_packet.SessionID <= 0)
                return;

            RpcObject rpcObj;
            if (EnumRequestType.Response == _packet.RequestType)
            {
                if (m_dictRequestSession.TryGetValue(_packet.SessionID, out rpcObj))
                {
                    Log.WriteInfo("Received a server response net packet! Session ID -> {0}", _packet.SessionID);
                    m_dictRequestSession.Remove(_packet.SessionID);
                    rpcObj.Dispatch(_packet);
                }
                else
                {
                    Log.WriteError("Received a unknow server response net packet! Session ID -> {0}", _packet.SessionID);
                }
            }
            else
            {
                Log.WriteInfo("Received a server request net packet! Session ID -> {0}", _packet.SessionID);
                NetMsg msg = ReceivedEvent?.Invoke(_packet);
                _socket.SendData(msg);
            }   
        }
    }
}
